package top.zhangjianyong.tools.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import top.zhangjianyong.tools.constant.MaiRuiApiPath;
import top.zhangjianyong.tools.constant.MaiRuiLevel;
import top.zhangjianyong.tools.entity.marirui.*;
import top.zhangjianyong.tools.exception.MairuiException;
import top.zhangjianyong.tools.exception.MairuiNoTimesException;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.List;

import static top.zhangjianyong.tools.constant.MaiRuiApiPath.*;

/**
 * @author ： zhangjianyong
 * @date ： 2022/10/12 10:06 AM
 */
@Slf4j
@Component
public class MaiRuiApiUtil {

    private LocalDateTime lastTime;
    @Value("${mairui.licence}")
    private String LICENCE;
    @Value("${mairui.times}")
    private Integer times;

    public void init(String licence) {
        this.LICENCE = licence;
        this.times = 1;
    }

    private void sleep() {
        LocalDateTime now = LocalDateTime.now();
        if (lastTime != null && lastTime.plusSeconds(3).isAfter(now)) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            sleep();
        }
        lastTime = now;
    }

    private String doGet(MaiRuiApiPath apiPath) {
        return doGet(apiPath.getUrl(LICENCE));
    }

    private String doGet(MaiRuiApiPath apiPath, String code) {
        return doGet(apiPath.getUrl(code, LICENCE));
    }

    private String doGet(MaiRuiApiPath apiPath, String code, MaiRuiLevel level) {
        return doGet(apiPath.getUrl(code, level, LICENCE));
    }

    private synchronized String doGet(String url) {
        return doGet(url, times);
    }

    private String doGet(String url, int time) {
        sleep();
        HttpRequest get = HttpUtil.createGet(url);
        String body;
        try (HttpResponse execute = get.execute()) {
            body = execute.body();
        }
        log.info("[接口返回] {}", body);
        if ("101".equals(body)) {
            throw new MairuiNoTimesException("接口次数已使用完毕");
        }
        if (!StringUtils.isBlank(body)
            && !"{}".equals(body)
            && !"[]".equals(body)) {
            return body;
        }
        if (time <= 0) {
            //throw new MairuiException("接口返回数据为空");
            return body;
        }
        try {
            long sleepTime = (times - time + 1) * 3000;
            log.info("[麦蕊接口] 重试等待：{}", sleepTime);
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("[麦蕊接口] 请求重试,{}", time);
        return doGet(url, time - 1);
    }


    public List<JJ> JJAll() {
        log.info("[获取基金]");
        String body = doGet(JJ_ALL);
        return JSONObject.parseArray(body, JJ.class);
    }

    public JJGK JJGK(String dm) {
        return JJGK(dm, times);
    }

    public JJGK JJGK(String dm, Integer time) {
        log.info("[基金概况] {}, {}", dm, time);
        String body = doGet(JJ_JJGK, dm);
        JJGK jjgk = JSONObject.parseObject(body, JJGK.class);
        if (!StringUtils.isBlank(jjgk.getDm())) {
            return jjgk;
        }
        time = time - 1;
        if (time < 0) throw new MairuiException("[基金概况] 获取失败");
        return JJGK(dm, time);
    }

    public List<JJETF> JJETF() {
        log.info("[获取ETF]");
        String body = doGet(JJ_ETF);
        return JSONObject.parseArray(body, JJETF.class);
    }

    public JJETFHQ JJETFHQ(String code) {

        return JJETFHQ(code, 5);

    }

    public JJETFHQ JJETFHQ(String code, int times) {
        log.info("[实时行情] {}", code);
        String body = doGet(JJ_ETF_HQ, code);
        JJETFHQ jjetfhq = JSONObject.parseObject(body, JJETFHQ.class);
        if (StringUtils.isBlank(jjetfhq.getDm())) {
            if (body.contains("404 Not Found")) return null;
            if (times > 0) {
                return JJETFHQ(code, times - 1);
            } else {
                return null;
            }

        }
        return jjetfhq;

    }

    public List<JJLSJZ> JJLSJZ(String code) {
        log.info("[历史数据] {}", code);
        String body = doGet(JJ_LSJZ, code);
        return JSONObject.parseArray(body, JJLSJZ.class);

    }

    public JJZXKX JJZXKX(String code, MaiRuiLevel level) {
        log.info("[最新K值] {} {}", code, level);
        String body = doGet(JJ_ZXKX, code, level);
        return JSONObject.parseObject(body, JJZXKX.class);
    }

    public List<JJLSKX> JJLSKX(String code, MaiRuiLevel level) {
        log.info("[历史K值] {} {}", code, level);
        String body = doGet(JJ_LSKX, code, level);
        return JSONObject.parseArray(body, JJLSKX.class);
    }

    public List<JJZCPZ> JJZCPZ(String code) {
        log.info("[资产配置] {}", code);
        String body = doGet(JJ_ZCPZ, code);
        return JSONObject.parseArray(body, JJZCPZ.class);
    }

    public List<JJGPCC> JJGPCC(String code) {
        log.info("[股票持仓] {}", code);
        String body = doGet(JJ_GPCC, code);
        return JSONObject.parseArray(body, JJGPCC.class);
    }

    public HSRLSSJY HSRLSSJY(String code) {
        return HSRLSSJY(code, times);
    }

    public HSRLSSJY HSRLSSJY(String code, int time) {

        log.info("[实时股价] {},{}", code, time);
        String body = doGet(HSRL_SSJY, code);
        HSRLSSJY hsrlssjy = JSONObject.parseObject(body, HSRLSSJY.class);
        if (hsrlssjy.getP() != null) {
            return hsrlssjy;
        }
        time = time - 1;
        if (time < 0) throw new MairuiException("[实时股价] 获取失败," + code);
        return HSRLSSJY(code, time);
    }

    public List<HSCPCWZB> HSCPCWZB(String code) {
        log.info("[财务指标] {}", code);
        String body = doGet(HSCP_CWZB, code);
        return JSONObject.parseArray(body, HSCPCWZB.class);
    }

    public List<HSCPJDLR> HSCPJDLR(String code) {
        log.info("[季度利润] {} ", code);
        String body = doGet(HSCP_JDLR, code);
        return JSONObject.parseArray(body, HSCPJDLR.class);
    }

    public void HF_REAL_TIME(String code){
        log.info("[实时数据]{}",code);
        String body = doGet(HF_REAL_TIME,code);
        log.info(body);
    }

    /* sh588390 */
    public static void main(String[] args) throws FileNotFoundException {
        String code = "159001";
        InputStream inputStream = MaiRuiApiUtil.class.getClassLoader().getResourceAsStream("mairui.lic");

        String read = IoUtil.read(inputStream, Charset.defaultCharset());
        MaiRuiApiUtil util = new MaiRuiApiUtil();
        util.init(read);
       // JJETFHQ sh512660 = util.JJETFHQ("sh511220");
        List<JJLSKX> sh520500 = util.JJLSKX("sz159570", MaiRuiLevel.DAY);
        System.out.println(JSONObject.toJSONString(sh520500));

       // util.HF_REAL_TIME(code);

        //System.out.println(JSONObject.toJSONString(sh512660));
        // JJZXKX jjzxkx = util.JJZXKX("sh512690", MaiRuiLevel.DAY);
       /* List<JJLSKX> jjlskx = util.JJLSKX("sh512690", MaiRuiLevel.DAY);

        System.out.println(JSONObject.toJSONString(jjlskx));*/
/*
        List<String> list = Arrays.asList("512660",
                "512660",
                "512690",
                "159865",
                "512480",
                "159766",
                "515030",
                "517380",
                "561510",
                "159852",
                "561800");
        List<JJETF> jjetf = util.JJETF();
        Set<JJETF> collect = jjetf.stream()
                .filter(etf -> list.stream().anyMatch(s -> etf.getDm().contains(s))).collect(Collectors.toSet());
        System.out.println(JSONObject.toJSONString(collect));*/

    }
}
